﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using P113_GtMotion;
using Prism.Commands;
using Prism.Services.Dialogs;
using Prism.Mvvm;
using System.Timers;
namespace GTSDemo.ViewModels
{
    public class MotionControlVM : BindableBase
    {
        IDialogService _dialogService;
        IEnumerable<Motor> _motors => HardwareHelper.GetHardwareHelper().GetCurrentMotors();
        IEnumerable<P110_BaseMotion.Input> _inputs => HardwareHelper.GetHardwareHelper().GetCurrentInputs();
        IEnumerable<P110_BaseMotion.Output> _outputs => HardwareHelper.GetHardwareHelper().GetCurrentOutpus();
        private Timer _timer;
        private int _planPos;
        public int PlanPos
        {
            get => _planPos;
            set
            {
                _planPos = value;
                SetProperty(ref _planPos, value, nameof(PlanPos));
            }
        }
        private int _speedSelectIndex;
        public int SpeedSelectIndex
        {
            get => _speedSelectIndex;
            set
            {
                _speedSelectIndex = value;
            }
        }
        public DelegateCommand LoadedCommand { get; }
        public DelegateCommand<P110_BaseMotion.Output> OutputCheckChangedCommand { get; }
        public DelegateCommand<Motor> PositiveMouseDownCommand { get; }
        public DelegateCommand<Motor> NegativeMouseDownCommand { get; }
        public DelegateCommand<Motor> MoveToPlanPosCommand { get; }
        public DelegateCommand<Motor> MouseUpCommand { get; }
        public ObservableCollection<Motor> Motors { get; set; }
        public ObservableCollection<P110_BaseMotion.Input> SignalInputs { get; set; }
        public ObservableCollection<P110_BaseMotion.Output> SignalOutputs { get; set; }
        public MotionControlVM(IDialogService service)
        {
            _dialogService = service;
            LoadedCommand = new DelegateCommand(Loaded);
            OutputCheckChangedCommand = new DelegateCommand<P110_BaseMotion.Output>(OuputCheckChanged);
            PositiveMouseDownCommand = new DelegateCommand<Motor>(PositiveMouseDown);
            NegativeMouseDownCommand = new DelegateCommand<Motor>(NegativeMouseDown);
            MoveToPlanPosCommand = new DelegateCommand<Motor>(MoveToPlanPos);
            MouseUpCommand = new DelegateCommand<Motor>(MouseUp);
        }
        private void ChangedSpeed(Motor motor)
        {
            switch (SpeedSelectIndex)
            {
                default:
                case 0:
                    motor.EnableLowSpeed();
                    break;
                case 1:
                    motor.EnableMediumSpeed();
                    break;
                case 2:
                    motor.EnableHighSpeed();
                    break;
            }
        }
        private void MoveToPlanPos(Motor motor)
        {
            try
            {
                ChangedSpeed(motor);
                motor?.MoveToWithArrive(PlanPos);
            }
            catch (Exception exp)
            {
                var message = exp.StackTrace;
                _dialogService.ShowDialog("MessageDialog", new DialogParameters($"message={message}"), null);
            }
        }

        private void MouseUp(Motor motor)
        {
            try
            {
                motor.SmoothStop();
            }
            catch (Exception exp)
            {
                var message = exp.StackTrace;
                _dialogService.ShowDialog("MessageDialog", new DialogParameters($"message={message}"), null);
            }
        }

        private void NegativeMouseDown(Motor motor)
        {
            try
            {
                motor?.ContinueMove(false, motor.Parameter.LowProfile.MaxVel);
            }
            catch (Exception exp)
            {
                var message = exp.StackTrace;
                _dialogService.ShowDialog("MessageDialog", new DialogParameters($"message={message}"), null);
            }
        }

        private void PositiveMouseDown(Motor motor)
        {
            try
            {
                motor?.ContinueMove(true, motor.Parameter.LowProfile.MaxVel);
            }
            catch (Exception exp)
            {
                var message = exp.StackTrace;
                _dialogService.ShowDialog("MessageDialog", new DialogParameters($"message={message}"), null);
            }
        }

        private void OuputCheckChanged(P110_BaseMotion.Output output)
        {
            if (output.Read(false))
                output.SetActive();
            else
                output.SetInactive();
        }

        private void Loaded()
        {
            Motors = new ObservableCollection<Motor>(_motors);
            SignalInputs = new ObservableCollection<P110_BaseMotion.Input>(_inputs);
            SignalOutputs = new ObservableCollection<P110_BaseMotion.Output>(_outputs);
            RaisePropertyChanged(nameof(Motors));
            RaisePropertyChanged(nameof(SignalInputs));
            RaisePropertyChanged(nameof(SignalOutputs));
            _timer = new Timer(1000);
            _timer.Elapsed += Timer_Elapsed;
            _timer.Start();
        }

        private void Timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            _timer.Elapsed -= Timer_Elapsed;
            try
            {
                foreach (var input in SignalInputs)
                {
                    input.Read(false);
                }
                foreach (var motor in Motors)
                {
                    motor.GetCurrentPosition();
                }
                RaisePropertyChanged(nameof(SignalInputs));
                RaisePropertyChanged(nameof(Motors));
            }
            finally
            {
                _timer.Elapsed += Timer_Elapsed;
            }
        }
    }
}
